﻿package com.petermacko.utils {
	import flash.events.*;
	import flash.net.*;
	import flash.utils.getTimer;
	
	/**
	 * The Bandwidth class downloads a bitmap file, and benchmarks the client's
	 * bandwidth.
	 *  
	 * @example Sniffing the user's bandwidth:
	 * <listing>	
	 * import com.petermacko.managers.EventManager;
	 * import com.petermacko.utils.Bandwidth;
	 * 
     * var bs:Bandwidth = new Bandwidth();
     * em.handleEvents(bs,this,"onBS");
     * bs.detect();
     * public function onBSComplete():void
     * {
     * 		trace(Bandwidth.Speed);
     * 		trace(Bandwidth.Speed==Bandwidth.HIGH);
     * 		trace(Bandwidth.Speed==Bandwidth.MED);
     * 		trace(Bandwidth.Speed==Bandwidth.LOW);
     * 		//Bandwidth.Speed will be equal to Bandwidth.LOW / MED / HIGH. One of the three.
     * }
	 * </listing>
	 * 
	 * @see net.guttershark.control.DocumentController DocumentController class
	 */
	final public class Bandwidth extends EventDispatcher
	{
		public static const LOW:String = "low"; //Low bandwidth
		public static const MED:String = "med"; //Medium bandwidth
		public static const HIGH:String = "high"; //High bandwidth

		public static var Speed:String = null; //Pointer to which bandwidth is detected. Default is Bandwidth.MED
		private var di:URLRequest; //detectImage: The image to use in the detection script.
		public var l:URLLoader; //The loader used to load the bandwidth image.
		
		//startTime - st, endTime - et, totalBytes - tb, targetMedBandwidth - tmb, targetLowBandwidth - tlb
		private var st:Number, et:Number, tb:Number, tmb:Number, tlb:Number;
		private var b:uint; //bandwidth

		public function Bandwidth(image:URLRequest=null,tlb:Number=256,tmb:Number=550):void {
			if(!image) image = new URLRequest("./bandwidth.jpg");
			this.tlb = tlb;
			this.tmb = tmb;
			this.di = image;
			l = new URLLoader();
			l.addEventListener(Event.COMPLETE,onComplete);
		}
			
		//Inititiates the bandwidth detection process.
		public function detect():void {
			if(!di) throw new Error("You must supply an image to load.");
			et = 0;
			st = 0;
			tb = 0;
			b = 0;
			l.addEventListener(Event.OPEN,onStart,false,0,true);
			l.addEventListener(ProgressEvent.PROGRESS,onProgress,false,0,true);
			l.load(di);
		}
				
		//On start of the downloading.
		private function onStart(se:Event):void	{
			st = getTimer();
		}
		
		//When the image completes downloading.
		private function onComplete(ce:Event):void {
			et = getTimer();
			var kbytes:uint = (tb * 1000); //converts to kilobytes
			b = (kbytes / ((et - st) * 100)); //get Kbps
    		if(b < tlb) Bandwidth.Speed = Bandwidth.LOW;
    		else if(b < tmb) Bandwidth.Speed = Bandwidth.MED;
    		else Bandwidth.Speed = Bandwidth.HIGH;
			removeListeners();
			b = NaN;
			st = NaN;
			et = NaN;
			tb = NaN;
			di = null;
		}
		
		//On progress of the loader
		private function onProgress(pe:ProgressEvent):void {
			if(pe.bytesTotal > 0) tb = pe.bytesTotal;
		}
		
		//removes listeners on the URLLoader.
		private function removeListeners():void	{
			l.removeEventListener(Event.OPEN,onStart);
			l.removeEventListener(ProgressEvent.PROGRESS,onProgress);
			l.removeEventListener(Event.COMPLETE,onComplete);
		}
		
		//Dispose of internal variables.
		public function dispose():void {
			removeListeners();
			di = null;
			l = null;
			et = NaN;
			st = NaN;
			tlb = NaN;
			tmb = NaN;
			tb = NaN;
			b = NaN;
		}
	}
}